package com.jdd.modules.parking.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jdd.common.api.vo.ResultVo;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.util.RestTemplateUtils;
import com.jdd.modules.configcartype.entity.ConfigCarType;
import com.jdd.modules.configcartype.service.IConfigCarTypeService;
import com.jdd.modules.order.entity.ParkOrderInfo;
import com.jdd.modules.order.mapper.ParkOrderInfoMapper;
import com.jdd.modules.parking.entity.ParkArmInfo;
import com.jdd.modules.parking.entity.ParkCarEnterLog;
import com.jdd.modules.parking.entity.ParkCarOutLog;
import com.jdd.modules.parking.entity.ParkWorkStation;
import com.jdd.modules.parking.mapper.ParkArmInfoMapper;
import com.jdd.modules.parking.mapper.ParkCarEnterLogMapper;
import com.jdd.modules.parking.mapper.ParkCarOutLogMapper;
import com.jdd.modules.parking.mapper.ParkWorkStationMapper;
import com.jdd.modules.parking.service.IparkCarOutLogService;
import com.jdd.modules.parking.vo.MontiorSearchRespVo;
import com.jdd.modules.parking.vo.MontiorSearchVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 车辆车场信息
 * @Author: jdd
 * @Date: 2021-02-20
 * @Version: V1.0
 */
@Service
@Slf4j
public class ParkCarOutLogServiceImpl extends ServiceImpl<ParkCarOutLogMapper, ParkCarOutLog> implements IparkCarOutLogService {
    @Resource
    private ParkArmInfoMapper parkArmInfoMapper;
    @Resource
    private ParkWorkStationMapper parkWorkStationMapper;
    @Resource
    private ParkCarOutLogMapper parkCarOutLogMapper;
    @Resource
    private ParkCarEnterLogMapper parkCarEnterLogMapper;
    @Resource
    private IConfigCarTypeService carTypeService;
    @Resource
    private ParkOrderInfoMapper parkOrderInfoMapper;
    @Resource
    private RestTemplateUtils restTemplateUtils;

    private String springCloudUrl;

    @Override
    public Page<MontiorSearchRespVo> monitorList(MontiorSearchVo montiorSearchVo, Integer pageNo, Integer pageSize) throws Exception {
        if (ObjectUtil.isEmpty(montiorSearchVo)) {
            throw new Exception("查询参数为空");
        }
        if (ObjectUtil.isEmpty(montiorSearchVo.getWorkName())) {
            throw new Exception("查询工作站名称参数为空");
        }
        //车道序列号
        List<String> serials = null;
        //工作站
        ParkWorkStation station = parkWorkStationMapper.selectOne(new QueryWrapper<ParkWorkStation>().eq("work_name", montiorSearchVo.getWorkName()));
        if (ObjectUtil.isEmpty(station)) {
            throw new Exception("工作站不存在！！！");
        }
        //车道名称查询
        if (ObjectUtil.isEmpty(montiorSearchVo.getArmName())) {
            //通过选择车道查询
            String workName = montiorSearchVo.getWorkName();
            QueryWrapper<ParkArmInfo> armInfoQueryWrapper = new QueryWrapper<>();
            armInfoQueryWrapper.eq("work_station_name", workName);
            armInfoQueryWrapper.eq("arm_type", JddConstant.StringNumber.STRING_ONE);
            List<ParkArmInfo> parkArmInfos = parkArmInfoMapper.selectList(armInfoQueryWrapper);
            if (ObjectUtil.isEmpty(parkArmInfos)) {
                throw new Exception("通过工作站查询车道时为空");
            }
            serials = parkArmInfos.stream().map(ParkArmInfo::getSerialNo).collect(Collectors.toList());
        }
        //时间选择，应该大于当前工作站上班时间
        if (ObjectUtil.isEmpty(montiorSearchVo.getBeginTime())) {
            montiorSearchVo.setBeginTime(station.getUpTime());
        }
        //符合条件的入场纪录，这里要转换成传到前端的集合
        List<MontiorSearchRespVo> montiorSearchRespVos = parkCarOutLogMapper.monitorList(montiorSearchVo.getPlateNo(), montiorSearchVo.getArmName(), serials, montiorSearchVo.getSwichType(), montiorSearchVo.getBeginTime(), montiorSearchVo.getEndTime(), pageNo, pageSize);
        List<MontiorSearchRespVo> monitorListAll = parkCarOutLogMapper.monitorListAll(montiorSearchVo.getBeginTime());
        //加上备注和操作员的信息，转换车辆类型
        List<MontiorSearchRespVo> searchRespVos = montiorSearchRespVos.stream().map(item -> {
            item.setWorkName(station.getWorkName());
            item.setOperationName(station.getOperationName());
            item.setCarTypeName(getCarType(Integer.parseInt(item.getCarTypeName())));
            return item;
        }).collect(Collectors.toList());
        //转换成分页
        Page<MontiorSearchRespVo> page = new Page<>(pageNo, pageSize);
        //当前显示的数据
        page.setRecords(searchRespVos);
        //总页数
        page.setTotal(searchRespVos.size());
        //有多少页
        page.setPages(0L);
        if (ObjectUtil.isNotEmpty(monitorListAll) && ObjectUtil.isNotEmpty(montiorSearchRespVos)) {
            if (monitorListAll.size() % montiorSearchRespVos.size() > 0) {
                page.setPages(monitorListAll.size() / montiorSearchRespVos.size() + 1);
            } else {
                page.setPages(monitorListAll.size() / montiorSearchRespVos.size());
            }
        }
        return page;
    }

    @Override
    public Page<MontiorSearchRespVo> monitorParkList(MontiorSearchVo montiorSearchVo, Integer pageNo, Integer pageSize) throws Exception {
        if (ObjectUtil.isEmpty(montiorSearchVo)) {
            throw new Exception("查询参数为空");
        }
        if (ObjectUtil.isEmpty(montiorSearchVo.getWorkName())) {
            throw new Exception("查询工作站名称参数为空");
        }
        //车道序列号
        List<String> serials = null;
        //工作站
        ParkWorkStation station = parkWorkStationMapper.selectOne(new QueryWrapper<ParkWorkStation>().eq("work_name", montiorSearchVo.getWorkName()));
        if (ObjectUtil.isEmpty(station)) {
            throw new Exception("工作站不存在！！！");
        }
        //车道名称查询
        if (ObjectUtil.isEmpty(montiorSearchVo.getArmName())) {
            //通过选择车道查询
            String workName = montiorSearchVo.getWorkName();
            QueryWrapper<ParkArmInfo> armInfoQueryWrapper = new QueryWrapper<>();
            armInfoQueryWrapper.eq("work_station_name", workName);
            armInfoQueryWrapper.eq("arm_type", JddConstant.StringNumber.STRING_ZERO);
            List<ParkArmInfo> parkArmInfos = parkArmInfoMapper.selectList(armInfoQueryWrapper);
            if (ObjectUtil.isEmpty(parkArmInfos)) {
                throw new Exception("通过工作站查询车道时为空");
            }
            serials = parkArmInfos.stream().map(ParkArmInfo::getSerialNo).collect(Collectors.toList());
        }
        //时间选择，应该大于当前工作站上班时间
        if (ObjectUtil.isEmpty(montiorSearchVo.getBeginTime())) {
            montiorSearchVo.setBeginTime(station.getUpTime());
        }
        //符合条件的入场纪录，这里要转换成传到前端的集合
        List<MontiorSearchRespVo> montiorSearchRespVos = parkCarOutLogMapper.monitorList(montiorSearchVo.getPlateNo(), montiorSearchVo.getArmName(), serials, montiorSearchVo.getSwichType(), montiorSearchVo.getBeginTime(), montiorSearchVo.getEndTime(), pageNo, pageSize);
        List<MontiorSearchRespVo> monitorListAll = parkCarOutLogMapper.monitorListAll(montiorSearchVo.getBeginTime());
        // TODO: 2021/11/19
        //  总收费是最后一条的total_charge_fee,
        //  实际收费是查出的订单的charge_paid相加
        //  免费是查出的订单的coupon_amt相加
        //  抵扣统一0
        //  停车时长是最后一条的charge_duration
        //  加上备注和操作员的信息，转换车辆类型
        List<MontiorSearchRespVo> searchRespVos = montiorSearchRespVos.stream().map(item -> {
            //根据出场记录id去订单表查询
            ParkCarOutLog parkCarOutLog = parkCarOutLogMapper.selectById(item.getId());
            item.setOutTime(parkCarOutLog.getCarOutTime());
            item.setOutArmName(parkCarOutLog.getArmName());
            //根据入场纪录id查出入场的信息
            ParkCarEnterLog carEnterLog = parkCarEnterLogMapper.selectById(parkCarOutLog.getCarEnterId());
            item.setInArmName(carEnterLog.getArmName());
            item.setInTime(carEnterLog.getCarEnterTime());
            //总收费是最后一条的total_charge_fee
            List<ParkOrderInfo> orderInfos = parkOrderInfoMapper.getOrderByCarOutId(carEnterLog.getId());

            item.setWorkName(station.getWorkName());
            item.setOperationName(station.getOperationName());
            item.setCarTypeName(getCarType(Integer.parseInt(item.getCarTypeName())));
            return item;
        }).collect(Collectors.toList());
        //转换成分页
        Page<MontiorSearchRespVo> page = new Page<>(pageNo, pageSize);
        //当前显示的数据
        page.setRecords(searchRespVos);
        //总页数
        page.setTotal(monitorListAll.size());
        //有多少页
        page.setPages(0L);
        if (ObjectUtil.isNotEmpty(monitorListAll.size()) && ObjectUtil.isNotEmpty(montiorSearchRespVos.size())) {
            if (monitorListAll.size() % montiorSearchRespVos.size() > 0) {
                page.setPages(monitorListAll.size() / montiorSearchRespVos.size() + 1);
            } else {
                page.setPages(monitorListAll.size() / montiorSearchRespVos.size());
            }
        }
        return page;
    }

    /**
     * 无牌车出场识别信息放入云端缓存
     *
     * @param serialNo
     */
    @Override
    public void sendUnlicensedCarOut(String parkCode, String serialNo) {
        //组装参数
        MultiValueMap<String, String> request = new LinkedMultiValueMap<>();
        request.add("parkCode", parkCode);
        request.add("plateNo", "无牌车");
        request.add("serialNo", serialNo);
        // request.add("ossImg",ossImg);
        HttpHeaders headers = new HttpHeaders();
        // 以表单的方式提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> requests = new HttpEntity<>(request, headers);
        String urls = "";
        ResponseEntity<ResultVo> posts = null;
        try {
            posts = restTemplateUtils.post(urls, requests, ResultVo.class);
            if (posts != null) {
                ResultVo body = posts.getBody();
                if (null != body && body.getCode() == 200) {
                    log.info("无牌车出场识别信息放入云端缓存,成功");
                }
            }
        } catch (Exception e) {
            log.error("无牌车出场识别信息放入云端缓存接口异常", e.getMessage());
        }
    }

    /**
     * 获取最后一个出场记录
     *
     * @param parkCode
     * @return
     */
    @Override
    public ParkCarOutLog getLastParkOutEnterLog(String parkCode) {
        LambdaQueryWrapper<ParkCarOutLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkCarOutLog::getParkCode, parkCode);
        queryWrapper.orderByDesc(ParkCarOutLog::getCarOutTime);
        List<ParkCarOutLog> carEnterLogs = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(carEnterLogs)) {
            return null;
        }
        return carEnterLogs.get(0);
    }

    @Override
    public void updateSynchronousStatus(String id, String synchronousStatus) {
        ParkCarOutLog parkCarOutLog = new ParkCarOutLog();
        parkCarOutLog.setId(id);
        parkCarOutLog.setSynchronousStatus(synchronousStatus);
            this.updateById(parkCarOutLog);
    }

    /**
     * 根据入场ID 查询出场记录
     *
     * @param enterId 入场ID
     * @return 出场记录
     */
    @Override
    public ParkCarOutLog getParkOutEnterLogByEnterId(String enterId) {
        LambdaQueryWrapper<ParkCarOutLog> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ParkCarOutLog::getCarEnterId, enterId);
        queryWrapper.orderByDesc(ParkCarOutLog::getCarOutTime);
        List<ParkCarOutLog> parkCarOutLogs = this.list(queryWrapper);
        if (CollectionUtils.isEmpty(parkCarOutLogs)) {
            return null;
        }
        return parkCarOutLogs.get(0);
    }

    /**
     * 根据车辆编号、车牌类型匹配停车场的车辆类型Id
     *
     * @param type 车牌类型
     * @return java.lang.String
     * @version 1.0
     */
    private String getCarType(int type) {
        String result = null;
        List<ConfigCarType> list = carTypeService.getCarTypeList();
        for (ConfigCarType carType : list) {
            String carTypeName = carType.getCarTypeName();
            List<String> typeNo = Arrays.asList(carType.getCarTypeNo().split(","));
            if (typeNo.contains(type + "")) {
                result = carTypeName;
                return result;
            }
        }
        return result;
    }
}
